/* ---------------------------------------------- 头文件包含 ---------------------------------------------- */
#include "./SYSTEM/SYS/sys.h"
#include "./SYSTEM/Task/task_manager.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/USART/myusart.h"
#include "./BSP/LCD/lcd_init.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/LCD/pic.h"
#include "./BSP/TIMER/gtim.h"
#include "./BSP/24CXX/24cxx.h"
#include "./BSP/NORFLASH/norflash.h"
#include "./USMART/usmart.h"
#include "./sys_param/sys_param.h"
#include "main_menu.h"
#include "string.h"

/* --------------------------------------------- 日志标签定义 --------------------------------------------- */
#define LOG_TAG    "SYS"
#include "elog.h"

/* -------------------------------------------- 中断向量表控制 -------------------------------------------- */

/**
 * @brief       设置中断向量表偏移地址
 * @param       baseaddr: 基址
 * @param       offset: 偏移量
 * @retval      无
 */
void sys_nvic_set_vector_table(uint32_t baseaddr, uint32_t offset)
{
    /* 设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留 */
    SCB->VTOR = baseaddr | (offset & (uint32_t)0xFFFFFE00);
}

/* -------------------------------------------- 低功耗控制函数 -------------------------------------------- */

/**
 * @brief       执行WFI指令(执行完该指令进入低功耗状态, 等待中断唤醒)
 * @param       无
 * @retval      无
 */
void sys_wfi_set(void)
{
    __ASM volatile("wfi");
}

/**
 * @brief       进入待机模式
 * @param       无
 * @retval      无
 */
void sys_standby(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();    /* 使能电源时钟 */
    SET_BIT(PWR->CR, PWR_CR_PDDS); /* 进入待机模式 */
}

/* -------------------------------------------- 中断控制函数 ---------------------------------------------- */

/**
 * @brief       关闭所有中断(但是不包括fault和NMI中断)
 * @param       无
 * @retval      无
 */
void sys_intx_disable(void)
{
    __ASM volatile("cpsid i");
}

/**
 * @brief       开启所有中断
 * @param       无
 * @retval      无
 */
void sys_intx_enable(void)
{
    __ASM volatile("cpsie i");
}

/* -------------------------------------------- 系统控制函数 ---------------------------------------------- */

/**
 * @brief       设置栈顶地址
 * @note        左侧若出现红X, 属于MDK误报, 实际是没问题的
 * @param       addr: 栈顶地址
 * @retval      无
 */
void sys_msr_msp(uint32_t addr)
{
    __set_MSP(addr);    /* 设置栈顶地址 */
}

/**
 * @brief       系统软复位
 * @param       无
 * @retval      无
 */
void sys_soft_reset(void)
{
    NVIC_SystemReset();
}
/**
 * @brief 系统外设初始化
 * @details 初始化基础外设和驱动
 */
void SystemPeripheralInit(void)
{
    FML_KEY_Init();                 /* 按键初始化 */
    FML_LED_Init();                 /* LED初始化 */
    delay_init(72);                 /* 延时初始化 */
    usart_init(115200);             /* 串口初始化为115200 */
    
    rtc_init();                                 /* 初始化RTC */
    rtc_set_alarm(2025, 8, 15, 10, 20, 00);     /* 设置一次闹钟 */
    
//    usart_init(115200);                 /* 串口初始化为115200 */
    usmart_dev.init(72);                /* 初始化USMART */

    /* 超时时间计算：
    * Tout = (4 × 32 × 3125) / 40000 = 400000 / 40000 = 10秒
    * 考虑LSI误差，实际约为 6~14秒
    */
    iwdg_init(IWDG_PRESCALER_128, 3125);

    gtim_timx_pwm_chy_init(200 - 1, 7200 - 1);    /* 50Hz的PWM频率 */
}

/**
 * @brief EasyLogger初始化
 * @details 配置日志系统的格式和级别，包含各种高级功能
 */
static void EasyLoggerInit(void)
{
    /* 初始化 EasyLogger */
    elog_init();
    
    /* ---------------------------------------- 格式化输出配置 ---------------------------------------- */
    /* ASSERT级别：显示所有信息（用于严重错误） */
    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
    
    /* ERROR级别：显示级别、标签、时间、文件、行号 */
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME | ELOG_FMT_DIR | ELOG_FMT_LINE);
    
    /* WARN级别：显示级别、标签、时间 */
    elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    
    /* INFO级别：显示级别、标签、时间 */
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    
    /* DEBUG级别：显示详细信息但排除函数名和线程信息 */
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    
    /* VERBOSE级别：显示详细信息但排除函数名和线程信息 */
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    
    /* ------------------------------------------ 过滤器配置 ------------------------------------------- */
    /* 设置全局日志级别过滤（只显示INFO及以上级别的日志）*/
    elog_set_filter_lvl(ELOG_LVL_INFO);
    
    /* 设置标签过滤（只显示特定标签的日志）*/
    // elog_set_filter_tag("FLOW_DRV");
    
    /* 设置关键字过滤（只显示包含特定关键字的日志）*/
    // elog_set_filter_kw("error");
    
    /* 为不同标签设置不同的日志级别 */
    // elog_set_filter_tag_lvl("SYS", ELOG_LVL_DEBUG);         /* SYS系统模块显示DEBUG级别 */
    
    /* 完全屏蔽某些模块的日志 */
    // elog_set_filter_tag_lvl("UNWANTED_MODULE", ELOG_FILTER_LVL_SILENT);  /* 完全屏蔽 */
    
    /* 其他过滤选项 */
    // elog_set_filter_lvl(ELOG_LVL_INFO);        /* 全局只显示INFO及以上级别 */
    // elog_set_filter_tag("FLOW_DRV");           /* 只显示FLOW_DRV标签的日志 */
    // elog_set_filter_kw("error");               /* 只显示包含"error"关键字的日志 */
    
    /* ------------------------------------------ 颜色输出配置 ------------------------------------------ */
    /* 启用颜色输出（需要在elog_cfg.h中启用ELOG_COLOR_ENABLE）*/
    // elog_set_text_color_enabled(true);
    
    /* ------------------------------------------- 输出锁配置 ------------------------------------------ */
    /* 禁用输出锁*/
    elog_output_lock_enabled(false);
    
    /* ----------------------------------------- 缓冲输出配置 ------------------------------------------- */
    /* 启用缓冲输出（需要在elog_cfg.h中启用ELOG_BUF_OUTPUT_ENABLE）*/
    // elog_buf_enabled(true);
    
    /* ----------------------------------------- 异步输出配置 ------------------------------------------ */
    /* 启用异步输出（需要在elog_cfg.h中启用ELOG_ASYNC_OUTPUT_ENABLE）*/
    // elog_async_enabled(true);
    
    /* ---------------------------------------- 启动 EasyLogger --------------------------------------- */
    elog_start();
    
    /* ------------------------------------------ 测试日志输出 ------------------------------------------- */
    log_i("EasyLogger初始化完成，当前配置:");
    log_i("- 全局输出级别: %s", "INFO");
    log_i("- 输出锁: %s", "禁用");
    log_i("- 颜色输出: %s", "禁用");
    log_d("这是一条DEBUG级别的测试日志");
    log_w("这是一条WARN级别的测试日志");
    log_e("这是一条ERROR级别的测试日志");
}

/**
 * @brief 系统模块初始化
 * @details 初始化各功能模块
 */
void SystemModuleInit(void)
{
    EasyLoggerInit();                       /* 初始化日志系统 */

    usmart_dev.init(72);                    /* 初始化USMART */
    at24cxx_init();                         /* 初始化24C02 */
    norflash_init();                        /* 初始化Norflash*/
    
    InitParam(true);                        /* 初始化参数系统 */
    ShowAllParam();                         /* 显示所有参数 */
    
    LCD_Init();                             /* 初始化LCD */
    ApplyDisplaySettings();                 /* 应用屏幕设置 */

    MainMenu_Init();                        /* 初始化菜单系统 */
}

/**
 * @brief 系统任务初始化
 * @details 创建和启动系统任务
 */
void SystemTaskInit(void)
{
    cotTask_Init();
    cotTask_Creat(ScanKeyTask, 20, 5);              /* 按键扫描任务，20ms执行一次 */
    cotTask_Creat(ScanLedTask, 20, 6);              /* LED控制任务，20ms执行一次 */
    cotTask_Creat(WatchdogTask, 1000, 5);           /* 喂狗任务，1秒执行一次 */
//    cotTask_Creat(RTCDisplayTask, 100, 7);          /* RTC时钟显示任务，100ms执行一次 */
//    cotTask_Creat(TestScheduleTask, 1000, 8);       /* 测试调度任务，1秒执行一次 */
    cotTask_Start();
}
